package com.lcf.framework.config;

import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.same.SaSameUtil;
import cn.hutool.json.JSONUtil;
import com.lcf.base.model.R;
import com.lcf.base.utils.UrlUtils;
import com.lcf.common.utils.ServletUtils;
import com.lcf.framework.interceptor.TenantInterceptor;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;
import java.util.Optional;

/**
 * 描述：satoken
 *
 * @author lcf
 * @since 2025/2/22 15:56
 */
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    private static final Logger log = LoggerFactory.getLogger(SaTokenConfigure.class);

    @Resource
    private SameTokenIgnoreConfig sameTokenIgnoreConfig;
    @Resource
    private TenantInterceptor tenantInterceptor;

    /**
     * 注册 Sa-Token 拦截器，打开注解式鉴权功能
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 将租户id放到线程变量中
        registry.addInterceptor(tenantInterceptor).addPathPatterns("/**");
        // 注册 Sa-Token 拦截器，打开注解式鉴权功能
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
    }

    /**
     * 注册 Sa-Token 全局过滤器
     * 内部服务外网隔离，使得请求只能通过网关访问，不能直接访问子服务
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        List<String> urls = sameTokenIgnoreConfig.getUrls();
        return new SaServletFilter()
                .addInclude("/**")
                .setAuth(obj -> {
                    String requestUrl = Optional.ofNullable(ServletUtils.getRequest()).map(HttpServletRequest::getServletPath).orElse(null);
                    if (UrlUtils.matchUrl(urls, requestUrl)) {
                        return;
                    }
                    // 校验 Same-Token 身份凭证
                    SaSameUtil.checkCurrentRequestToken();
                })
                .setError(e -> {
                    log.error(e.getMessage(), e);

                    return JSONUtil.parse(R.fail());
                });
    }
}

